package hu.raholec.service.jackrabbit;

import hu.raholec.data.BreadCrumbElement;
import hu.raholec.data.BreadCrumbList;
import hu.raholec.data.Content;
import hu.raholec.service.ContentService;
import hu.raholec.service.ServiceException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.jackrabbit.commons.JcrUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service
@Scope("singleton")
public class JackrabbitContentService implements ContentService {

    private static final String URL = "!!!!!!!!!!!!!!!!!!/repository.xml";
//    private static final String URL = "d:/STS/JCR_Repository/repository.xml";
    private static final String LOGINNAME = "admin";
    private static final String PASSWORD = "admin";
    private static final String APP_NAME = "RAHOLEC";
    private JackrabbitUtil util;

    public JackrabbitContentService() {
        util = new JackrabbitUtil(URL, LOGINNAME, PASSWORD);
    }

    private Node getRoot(Session s) {
        try {
            System.out.println("...");
            System.out.println("get or add root");
            Node myroot = JcrUtils.getOrAddNode(s.getRootNode(), APP_NAME);
            System.out.println("get or add users");
            JcrUtils.getOrAddNode(myroot, "users");
            System.out.println("get or add pictures");
            JcrUtils.getOrAddNode(myroot, "pictures");
            System.out.println("myroot: " + myroot.getPath() + " :: " + myroot.getName());
            System.out.println("...");
            
            return myroot;
        } catch (RepositoryException e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Content getContent(String path) {
    	Session s = util.login();
        try {
            Content c = convert(JcrUtils.getNodeIfExists(getRoot(s), path));
            s.save();
            util.logout(s);
            return c;
        } catch (RepositoryException e) {
            throw new ServiceException(e);
        } finally {
            util.logout(s);
        }
    }

    @Override
    public void addNode(String path, String nodeName) {
        System.out.println("addNode(" + path + ", " + nodeName + ")");
        Session s = util.login();
        try {
            Node base = JcrUtils.getNodeIfExists(getRoot(s), path);
            JcrUtils.getOrAddNode(base, nodeName);
            s.save();
            util.logout(s);
        } catch (RepositoryException e) {
            throw new ServiceException(e);
        } finally {
            util.logout(s);
        }
    }

    @Override
    public void addProperty(String path, String propertyName, String propertyValue) {
        Session s = util.login();
        try {
            Node base = JcrUtils.getNodeIfExists(getRoot(s), path);
            base.setProperty(propertyName, propertyValue);
            s.save();
            util.logout(s);
        } catch (RepositoryException e) {
            throw new ServiceException(e);
        } finally {
            util.logout(s);
        }
    }
    
    @Override
	public BreadCrumbList getBreadCrumb(String path) {
		// TODO Auto-generated method stub
		if (path.indexOf('/') == -1) {
			BreadCrumbList root = new BreadCrumbList();
			root.add(new BreadCrumbElement("users", "users"));
			return root;
		}
		String[] element = path.split("/");
    	BreadCrumbList parent = getBreadCrumb(path.replaceAll("/[^/]*$", ""));
    	parent.add(new BreadCrumbElement(element[element.length - 1], path));
    	System.out.println(parent.toString());
    	return parent;
	}
    

    private Content convert(Node node) throws RepositoryException {

        if (node == null) {
            return null;
        }

        Content content = new Content();
        content.setNodeNames(new HashSet<String>());
        content.setProperties(new HashMap<String, String>());

        if (node.hasNodes()) {
            for (Iterator<Node> it = JcrUtils.getChildNodes(node).iterator(); it.hasNext();) {
                Node n = it.next();
                content.getNodeNames().add(n.getName());
            }
        }

        if (node.hasProperties()) {
            for (Iterator<Property> it = JcrUtils.getProperties(node).iterator(); it.hasNext();) {
                Property p = it.next();
                content.getProperties().put(p.getName(), p.getString());
            }
        }

        return content;
    }
}
